package com.yun.service;

import com.yun.mapper.TPermissionMapper;
import com.yun.mapper.TRoleMapper;
import com.yun.mapper.UserMapper;
import com.yun.pojo.TPermission;
import com.yun.pojo.TRole;
import com.yun.pojo.UpdPwd;
import com.yun.pojo.User;
import com.yun.unit.Code;
import com.yun.unit.LoginUser;
import com.yun.unit.MD5Unit;
import com.yun.unit.R;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private TPermissionMapper permissionMapper;
    @Autowired
    private TRoleMapper tRoleMapper;
    //注册操作
    @Override
    public R register(User user) {
        user.setUserPic("https://myoss-shop.oss-cn-beijing.aliyuncs.com/09ac5bb6b92a-avatar.jpg");
        user.setNickname("用户"+UUID.randomUUID().toString().substring(24));
        //将密码进行md5加密
        String encrypt = MD5Unit.encrypt(user.getPassword());
        //重新赋值加密后的密码
        user.setPassword(encrypt);
        //向数据库添加数据
        int insert = userMapper.insert(user);
        if (insert > 0) {
            return new R(Code.save_ok,"注册成功");
        }
        return new R(Code.save_err,"注册失败");
    }
    //登录操作
    @Override
    public R login(User user) {
        User login = userMapper.login(user.getUsername());
        if (login == null){
            return new R(Code.get_err,"该用户不存在");
        }else {
            //将前端传输过来的密码进行加密
            //MD5Unit.encrypt(user.getPassword()
            //login.getPassword().equals数据库中查询出的密码
            String encrypt = MD5Unit.encrypt(user.getPassword());
            if (login.getPassword().equals(encrypt)){
                //当登录成功，将用户信息存放到一个对象中，放到redis中
                LoginUser loginUser = new LoginUser();
                loginUser.setUsername(login.getUsername());
                loginUser.setPassword(encrypt);
                List<TPermission> tPermissions = permissionMapper.selectAllById(login.getId());
                List<String> key1 = new ArrayList<>();
                //提取权限
                //遍历
                for (TPermission tPermission : tPermissions){
                    key1.add(tPermission.getKeyword());
                }
                List<TRole> tRoles = tRoleMapper.selectAllById(login.getId());
                //使用Stream提取角色
                List<String> key2 = tRoles.stream().map(item->item.getKeyword()).collect(Collectors.toList());

                //将角色和权限存放到一个集合中
                List<String> keyAll = new ArrayList<>();
                keyAll.addAll(key1);
                keyAll.addAll(key2);
                //存放到对象中
                loginUser.setJueseheguize(keyAll);
                //存放到redis中
                redisTemplate.opsForValue().set(login.getUsername(),loginUser);
                //然后用户名做为jwt的私有信息,生成一个jwt字符串
                //生成一个jwt
                String jwt ="";
                //日历
                Calendar calendar = Calendar.getInstance();
                Date time = calendar.getTime();//获取当前时间
                calendar.add(Calendar.MINUTE,30);
                Date time1 = calendar.getTime();//在当前时间之后的30分钟
                /**
                 * signWith(SignatureAlgorithm.HS256,"cmxh");
                 * 第一个参数是 加密方式
                 * 第二个参数是 秘钥
                 */
                JwtBuilder cmxh = Jwts.builder().setExpiration(time1).setIssuedAt(time).signWith(SignatureAlgorithm.HS256, "cmxh");
                //配置私有信息
                Map map = new HashMap();
                map.put("username",login.getUsername());
                cmxh.addClaims(map);
                System.out.println(cmxh);
                // 通过JwtBuilder对象的compact这个方法来生成JWT字符串
                jwt = cmxh.compact();
                System.out.println(jwt);
                //将用户信息和jwt存放到一个map集合中，返回给前端
                Map<String,Object> map1 = new HashMap();
                map1.put("xinxi",login);
                map1.put("token",jwt.toString());
                return new R(Code.get_ok,"登录成功",map1);
            }else {
                return new R(Code.get_err,"密码错误");
            }
        }
    }
    //忘记密码
    @Override
    public R forget(User user) {
        String encrypt = MD5Unit.encrypt(user.getPassword());
        user.setPassword(encrypt);
        int update = userMapper.update(user);
        if (update > 0){
            return new R(Code.update_ok,"修改成功");
        }
        return new R(Code.update_err,"修改失败");
    }
    //修改密码
    @Override
    public R updatePassword(UpdPwd user) {
        if (user.getNewpwd().equals(user.getOldpwd())){
            return new R(Code.update_err,"新密码不能与旧密码相同");
        }else {
            //将新密码和旧密码进行加密
            String newpwd = MD5Unit.encrypt(user.getNewpwd());
            String old = MD5Unit.encrypt(user.getOldpwd());
            //重新传到这个对象中
            user.setOldpwd(old);
            user.setNewpwd(newpwd);
            //将这个对象传输到数据层进行修改
            int update = userMapper.updatePassword(user);
            if (update > 0){
                return new R(Code.update_ok,"修改成功");
            }else {
                return new R(Code.update_err,"修改失败");
            }
        }
    }

    //修改用户信息
    @Override
    public R updateUser(User user) {
        int i = userMapper.updateUser(user);
        if (i > 0){
            return new R(Code.update_ok,"修改成功");
        }
        return new R(Code.update_err,"请稍后再试");
    }
    //保存头像的路径到数据库中
    @Override
    public R updateImgUrl(User user) {
        int i = userMapper.updateImgUrl(user);
        if (i > 0){
            return new R(Code.update_ok,"上传成功");
        }
        return new R(Code.update_err,"上传失败");
    }

    //根据用户id查询用户信息
    @Override
    public R selById(Integer id) {
        User user = userMapper.selById(id);
        if (user != null){
            return new R(Code.get_ok,"查询成功",user);
        }
        return new R(Code.get_err,"查询失败");
    }
}
